﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Collections.Specialized;
using System.Data.Linq;

using Ample.Model;

namespace Ample.DAL
{
    public class OrderManager : DBBase
    {
        public static OrderManager Create()
        {
            return new OrderManager();
        }

        #region Select Methods

        public IEnumerable<Order> GetOrders()
        {
            using (AmpleDataContext context = DataContext)
            {
                return context.AMPLE_Orders_SelectManual().ToArray<Order>();
            }
        }

        public IEnumerable<Order>  GetOrdersRecentStatusByUsername(string username)
        {
            using (AmpleDataContext context = DataContext)
            {
                context.LoadOptions = OrderLinqQueries.OrderStatus_Options_With_Order;

                return OrderLinqQueries.CompiledQuery_GetOrderWithLatestStatusByUsername(context, username).ToArray<Order>();
            }
        }

        public IEnumerable<Order> GetOrdersRecentStatus(string status, DateTime from, DateTime to)
        {
            using (AmpleDataContext context = DataContext)
            {
                context.LoadOptions = OrderLinqQueries.OrderStatus_Options_With_Order;

                return OrderLinqQueries.CompiledQuery_GetOrderWithLatestStatus(context, status, from, to).ToArray<Order>();
            }
        }

        public Order GetOrderByNo(string orderNo)
        {
            using (AmpleDataContext context = DataContext)
            {
                context.LoadOptions = OrderLinqQueries.OrderStatus_Options_With_Order;

                return OrderLinqQueries.CompiledQuery_GetOrderByOrderNo(context, orderNo).SingleOrDefault();
            }
        }

        public Order GetOrderById(int orderId)
        {
            using (AmpleDataContext context = DataContext)
            {
                context.LoadOptions = OrderLinqQueries.OrderStatus_Options_With_Order;

                return OrderLinqQueries.CompiledQuery_GetOrderByOrderId(context, orderId).SingleOrDefault();
            }
        }

        public IEnumerable<Order> GetOrderByUsername(string username)
        {
            using (AmpleDataContext context = DataContext)
            {
                var dlo = new DataLoadOptions();
                dlo.LoadWith<Order>(o => o.OrderStatuses);
                dlo.LoadWith<Order>(o => o.BoardUser);
                context.LoadOptions = dlo;

                return context.Orders.Where(o => o.User.UserName == username).ToList<Order>();
            }
        }

        public static StringCollection GetOrderStatuses(bool insertEmpty)
        {
            var sc = new StringCollection();
            sc.AddRange(Enum.GetNames(Type.GetType("Ample.DAL.Store.PaymentStatus")));
            return sc;
        }

        #endregion

        #region Update Methods

        public OperationStatus UpdateOrder(Order order)
        {
            AmpleDataContext context = null;
            try
            {
                context = DataContext;
                context.AMPLE_Orders_Update(
                    order.OrderId,
                    order.AddedDate,
                    order.SubTotal);
            }
            catch (Exception exp)
            {
                return new OperationStatus(false, exp.Message, exp);
            }
            finally
            {
                if (context != null) context.Dispose();
            }
            return new OperationStatus(true, null, null);
        }

        public OperationStatus UpdateOrderImplicit(Order order)
        {
            AmpleDataContext context = null;
            try
            {
                context = DataContext;

                context.Orders.Attach(order, true);
                context.Refresh(RefreshMode.OverwriteCurrentValues, order);

                context.OrderStatuses.InsertAllOnSubmit(order.OrderStatuses);
                
                context.SubmitChanges();
            }
            catch (ChangeConflictException)
            {
                context.ChangeConflicts.ResolveAll(RefreshMode.KeepCurrentValues);
                context.SubmitChanges();
            }
            catch (Exception exp)
            {
                return new OperationStatus(false, exp.Message, exp);
            }
            finally
            {
                //if (context != null) context.Dispose();
            }
            return new OperationStatus(true, null, null);
        }


        #endregion

        #region Insert Methods

        public OperationStatus InsertOrder(Order order)
        {
            AmpleDataContext context = null;
            try
            {
                context = DataContext;

                context.Orders.InsertOnSubmit(order);
                context.SubmitChanges();
            }
            catch (Exception exp)
            {
                return new OperationStatus(false, exp.Message, exp);
            }
            finally
            {
                if (context != null) context.Dispose();
            }
            return new OperationStatus(true, null, null, order.OrderId);
        }

        public string GenerateOrderNo()
        {
            using (AmpleDataContext context = DataContext)
            {
                string orderNo = context.Orders.ToList().Max(o => Int32.Parse(o.OrderNo)).ToString();
                
                if(orderNo != null)
                {
                    int result;
                    Int32.TryParse(orderNo, out result);
                    
                    ++result;

                    orderNo = result.ToString();
                }
                else
                    orderNo = "10001";
                
                return orderNo;
            }
        }
        
        #endregion

        #region Delete Methods

        public OperationStatus DeleteOrder(Order order)
        {
            AmpleDataContext context = null;
            try
            {
                context = DataContext;
                context.AMPLE_Orders_Delete(order.OrderId);
            }
            catch (Exception exp)
            {
                return new OperationStatus(false, exp.Message, exp);
            }
            finally
            {
                if (context != null) context.Dispose();
            }
            return new OperationStatus(true, null, null);
        }

        public OperationStatus DeleteOrder(int Id)
        {
            AmpleDataContext context = null;
            try
            {
                context = DataContext;
                context.AMPLE_Orders_Delete(Id);
            }
            catch (Exception exp)
            {
                return new OperationStatus(false, exp.Message, exp);
            }
            finally
            {
                if (context != null) context.Dispose();
            }
            return new OperationStatus(true, null, null);
        }


        #endregion

    }
}
